package com.crowntit.domain.order.service;


import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson2.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.crowntit.domain.order.adapter.event.PaySuccessMessageEvent;
import com.crowntit.domain.order.adapter.port.IGroupBuyMarketPort;
import com.crowntit.domain.order.adapter.port.IProductPort;
import com.crowntit.domain.order.adapter.port.IPublisherPort;
import com.crowntit.domain.order.adapter.repository.IOrderRepository;
import com.crowntit.domain.order.model.aggregate.CreateOrderAggregate;
import com.crowntit.domain.order.model.entity.*;
import com.crowntit.domain.order.model.valobj.OrderStatusVO;
import com.crowntit.types.enums.GroupBuyServiceResponseStatusEnum;
import com.crowntit.types.event.BaseEvent;
import com.google.common.eventbus.EventBus;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.List;

@Slf4j
@Service
public class OrderService extends AbstractOrderService{

    @Value("${alipay.return_url}")
    private String returnUrl;
    @Value("${alipay.notify_url}")
    private String notifyUrl;

    @Value("${gbm.notify-url}")
    private String gbmNotifyUrl;
    @Value("${default-product.product-id}")
    private String defaultProductId;

    @Resource
    private AlipayClient alipayClient;
    @Resource
    private IGroupBuyMarketPort groupBuyMarketPort;
    @Resource
    private EventBus eventBus;
    @Resource
    private PaySuccessMessageEvent paySuccessMessageEvent;
    @Resource
    private IPublisherPort publisher;

    @Value("${spring.rabbitmq.config.producer.topic_order_pay_success.routing_key}")
    private String routingKey;

    public OrderService(IOrderRepository repository, IProductPort port) {
        super(repository, port);
    }

    @Override
    protected void doSaveOrder(CreateOrderAggregate orderAggregate) {
        repository.doSaveOrder(orderAggregate);
    }

    @Override
    protected BigDecimal lockGroupBuyOrder(ShopCartEntity shopCartEntity, OrderEntity order) throws Exception {
        String userId = shopCartEntity.getUserId();
        String productId = shopCartEntity.getProductId();
        Long activityId = shopCartEntity.getActivityId();
        String teamId = shopCartEntity.getTeamId();

        GroupBuyLockInfoEntity groupBuyLockInfoEntity = groupBuyMarketPort.lockMarketOrder(GroupBuyLockServiceReqEntity.builder()
                .activityId(activityId)
                .teamId(teamId)
                .productId(productId)
                .userId(userId)
                .notifyUrl(gbmNotifyUrl)
                .outTradeNo(RandomStringUtils.randomNumeric(9))
                .build());

        groupBuyLockInfoEntity.setOriginalPrice(order.getOriginalPrice());
        if (groupBuyLockInfoEntity.getGroupBuyServiceResponseStatus().equals(GroupBuyServiceResponseStatusEnum.EXCEPTION_LOCK.getInfo())) {
            groupBuyLockInfoEntity.setPayPrice(order.getTotalAmount());
        }

        repository.updateOrderGroupBuyInfo(OrderEntity.builder()
                .orderId(order.getOrderId())
                .originalPrice(groupBuyLockInfoEntity.getOriginalPrice())
                .deductionPrice(groupBuyLockInfoEntity.getDeductionPrice())
                .payPrice(groupBuyLockInfoEntity.getPayPrice())
                .gbmOutTradeNo(groupBuyLockInfoEntity.getGbmOutTradeNo())
                .isGroupBuy(groupBuyLockInfoEntity.getIsGroupBuy())
                .groupBuyServiceResponseStatus(groupBuyLockInfoEntity.getGroupBuyServiceResponseStatus())
                .build());
        return groupBuyLockInfoEntity.getPayPrice();
    }

    @Override
    protected PayOrderEntity doPrepayOrder(String userId, String productId, String productName, String orderId, BigDecimal totalAmount) throws AlipayApiException {
        AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
        request.setNotifyUrl(notifyUrl);
        request.setReturnUrl(returnUrl);

        JSONObject bizContent = new JSONObject();
        bizContent.put("out_trade_no", orderId);
        bizContent.put("total_amount", totalAmount.toString());
        bizContent.put("subject", productName);
        bizContent.put("product_code", "FAST_INSTANT_TRADE_PAY");
        request.setBizContent(bizContent.toString());

        String form = alipayClient.pageExecute(request).getBody();

        PayOrderEntity payOrder = new PayOrderEntity();
        payOrder.setPayUrl(form);
        payOrder.setStatus(OrderStatusVO.PAY_WAIT);
        payOrder.setOrderId(orderId);

        repository.updateOrderPayInfo(payOrder);

        return payOrder;
    }

    @Override
    public void changeOrderPaySuccess(String orderId) throws IOException {
        log.info("支付成功，修改订单状态");
        OrderPaySuccessEntity paySuccessEntity = OrderPaySuccessEntity.builder()
                .orderId(orderId)
                .build();

        // 修改当前系统的数据
        repository.changeOrderPaySuccess(paySuccessEntity);

        // 查数据库：订单是否为团购订单
        GroupBuyStatusEntity groupBuyStatusEntity = repository.queryOrderGroupBuyStatusByOrderId(orderId);
        if (groupBuyStatusEntity.getIsGroupBuy() == 1) {
            log.info("支付成功，修改订单状态--检测到团购订单");
            // 团购交易结算
            GroupBuySettlementInfoEntity groupBuySettlementInfoEntity = groupBuyMarketPort.settlementMarketOrder(GroupBuySettlementServiceReqEntity.builder()
                    .outTradeNo(groupBuyStatusEntity.getGbmOutTradeNo())
                    .userId(groupBuyStatusEntity.getUserId())
                    .build());

            groupBuySettlementInfoEntity.setOrderId(orderId);
            repository.changeOrderGroupBuyStatus(groupBuySettlementInfoEntity);
        } else {
            // 非团购下单，结算后直接发布发货通知
            log.info("支付成功，发货通知");
            BaseEvent.EventMessage<PaySuccessMessageEvent.PaySuccessMassage> paySuccessMassageEventMessage = paySuccessMessageEvent.buildEventMessage(PaySuccessMessageEvent.PaySuccessMassage.builder()
                    .orderId(orderId)
                    .build());
            PaySuccessMessageEvent.PaySuccessMassage data = paySuccessMassageEventMessage.getData();
            String dataStr = JSON.toJSONString(data);
//            eventBus.post(dataStr);
            publisher.publish(routingKey, dataStr);
        }
    }

    @Override
    public void changeOrderGroupBuyTeamStatus(GroupBuyNotifyEntity groupBuyNotifyEntity) throws Exception {
        repository.changeGroupBuyOrdersStatus(groupBuyNotifyEntity);
        // todo: 之后可以补充一个定时查询超时未结算的团购订单的拼团状态的任务
    }

    @Override
    public List<String> queryNoPayNotifyOrder() {
        return repository.queryNoPayNotifyOrder();
    }

    @Override
    public List<String> queryTimeoutCloseOrder() {
        return repository.queryTimeoutCloseOrder();
    }

    @Override
    public boolean changeOrderClose(String orderId) {
        return repository.changeOrderClose(orderId);
    }
}
